package com.allen.study.application.api;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.allen.study.application.api.request.LeaveApplyApproveRequest;
import com.allen.study.application.api.request.LeaveApplyCreateRequest;
import com.allen.study.application.api.request.LeaveApplyQueryRequest;
import com.allen.study.application.api.request.LeaveApplyUpdateRequest;
import com.allen.study.application.api.response.LeaveApplyQueryResponse;
import com.allen.study.application.api.response.LeaveApplyResponse;
import com.allen.study.application.service.LeaveApplyAppService;
import com.allen.study.common.base.ApiPageResponse;
import com.allen.study.common.base.ApiResponse;
import com.allen.study.common.base.Pagination;
import com.allen.study.common.constants.LeaveApplyConstants;
import com.allen.study.common.utils.CamundaUtils;
import com.allen.study.domain.entity.EmployeeInfo;
import com.allen.study.domain.service.EmployeeInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Date;
import java.util.List;

import static com.allen.study.common.constants.LeaveApplyConstants.bpmnName;
import static com.allen.study.common.constants.LeaveApplyConstants.processDefinitionKey;

/**
 * 请假申请表接口
 *
 * @author AllenSun
 * @since 2025-04-23 20:46
 */
@RequestMapping(value = "/4.2.0/leaveapply")
@RestController
@AllArgsConstructor
@Tag(name = "请假申请表接口", description = "请假申请表接口")
@Slf4j
public class LeaveApplyApi {

    /**
     * 请假申请表应用服务
     */
    @Autowired
    private final LeaveApplyAppService leaveApplyAppService;

    @Autowired
    private final EmployeeInfoService employeeInfoService;

    /**
     * 创建请假申请表
     *
     * @param createRequest 请假申请表创建对象
     * @return 响应结果
     */
    @PostMapping
    @Operation(summary = "创建请假申请表", description = "创建请假申请表")
    public ApiResponse<Void> create(@RequestBody @Valid LeaveApplyCreateRequest createRequest) {
        return leaveApplyAppService.create(createRequest);
    }

    /**
     * 根据主键删除请假申请表
     *
     * @param leaveApplyId 请假申请表主键
     * @return 响应结果
     */
    @DeleteMapping(value = "/{leave_apply_id}")
    @Operation(summary = "根据主键删除请假申请表", description = "根据主键删除请假申请表")
    public ApiResponse<Void> deleteById(@PathVariable(name = "leave_apply_id") Long leaveApplyId) {
        return leaveApplyAppService.deleteById(leaveApplyId);
    }

    /**
     * 根据主键更新请假申请表
     *
     * @param leaveApplyId 请假申请表主键
     * @param updateRequest 请假申请表更新对象
     * @return 响应结果
     */
    @PutMapping(value = "/{leave_apply_id}")
    @Operation(summary = "根据主键更新请假申请表", description = "根据主键更新请假申请表")
    public ApiResponse<Void> updateById(@PathVariable(name = "leave_apply_id") Long leaveApplyId,
            @RequestBody @Valid LeaveApplyUpdateRequest updateRequest) {
        return leaveApplyAppService.updateById(leaveApplyId, updateRequest);
    }

    /**
     * 根据主键查询请假申请表详情
     *
     * @param leaveApplyId 请假申请表主键
     * @return 响应结果
     */
    @GetMapping(value = "/{leave_apply_id}")
    @Operation(summary = "根据主键查询请假申请表详情", description = "根据主键查询请假申请表详情")
    public ApiResponse<LeaveApplyResponse> queryById(@PathVariable(name = "leave_apply_id") Long leaveApplyId) {
        return leaveApplyAppService.queryById(leaveApplyId);
    }

    /**
     * 分页查询请假申请表
     *
     * @param pagination   分页
     * @param queryRequest 请假申请表查询对象
     * @return 响应结果
     */
    @GetMapping
    @Operation(summary = "分页查询请假申请表", description = "分页查询请假申请表")
    public ApiPageResponse<LeaveApplyQueryResponse> query(@Valid Pagination pagination, @Valid LeaveApplyQueryRequest queryRequest) {
        return leaveApplyAppService.query(pagination, queryRequest);
    }

    /**
     * 部署流程定义
     * @MethodName: deployProcess
     * @Author: AllenSun
     * @Date: 2025/2/22 下午10:25
     */
    @GetMapping("/deployProcess")
    public ApiResponse<String> deployProcess() {
        // 根据流程bpmn路径部署流程

        String bpmnPath = StrUtil.format("{}/{}", LeaveApplyConstants.bpmnPath,bpmnName);
        Deployment deployment = CamundaUtils.deployProcessByClasspath("测试用户审批：请假流程审批", bpmnPath);
        return ApiResponse.ok(deployment.toString());
    }

    /**
     * 查询已部署的流程，判断是否部署成功
     * @MethodName: selectProcessInstanceByKey
     * @Author: AllenSun
     * @Date: 2025/2/23 上午12:30
     */
    @GetMapping("/selectProcessInstanceByKey")
    public ApiResponse<String> selectProcessInstanceByKey() {
        // 查询部署流程
        ProcessDefinition processDefinition = CamundaUtils.selectProcessDefinitionByKey(processDefinitionKey);
        return ApiResponse.ok(processDefinition.toString());
    }

    /**
     * 根据流程定义key发起流程实例
     * @MethodName: startProcess
     * @Author: AllenSun
     * @Date: 2025/2/22 下午10:24
     */
    @GetMapping("/startProcess")
    public ApiResponse<LeaveApplyResponse> startProcess() {
        // 准备流程变量
        LeaveApplyCreateRequest leaveApply = new LeaveApplyCreateRequest();
        leaveApply.setEmployeeId(LeaveApplyConstants.employeeId);
        leaveApply.setStartDate(new Date());
        leaveApply.setEndDate(new Date());
        leaveApply.setDays(5);
        leaveApply.setReason("婚假");
        leaveApply.setLeaderId("10087");
        leaveApply.setPmId("10087");
        leaveApply.setSupervisorId("10087");
        leaveApply.setHandoverPerson(LeaveApplyConstants.handoverPerson);

        return leaveApplyAppService.apply(leaveApply);
    }

    //获取发起人的待处理任务
    @GetMapping("/getInitiatorTasks")
    public ApiResponse<List<Task>> getInitiatorTasks() {
        String manager = "10086";
        List<Task> tasksByAssignee = CamundaUtils.getTasksByAssignee(manager, 1, 10);
        return ApiResponse.ok(tasksByAssignee);
    }

    //获取组长的待处理任务
    // @GetMapping("/getLeaderTasks")
    // public ApiResponse<List<Task>> getLeaderTasks() {
    //     List<Task> tasksByAssignee = CamundaUtils.getTasksByAssignee(leaderId, 1, 10);
    //     return ApiResponse.ok(tasksByAssignee);
    // }

    //处理任务
    @GetMapping("/completeLeaderTask")
    public ApiResponse<String> completeTask() {
        LeaveApplyApproveRequest approvalRecordDTO = new LeaveApplyApproveRequest();
        approvalRecordDTO.setApproverId(LeaveApplyConstants.leaderId);
        approvalRecordDTO.setApprovalResult(true);
        approvalRecordDTO.setApprovalReason("组长说同意");
        approvalRecordDTO.setProcessInstanceId(LeaveApplyConstants.pocessInstanceId);
        leaveApplyAppService.approve(approvalRecordDTO);

        return ApiResponse.ok();
    }

    // TODO
    // （1）把审批记录的service和mapper方法补上
    // （2）审批通过和不通过，添加监听器，给发起人通知
    // （3）审批成功和失败，添加监听器，给发起人通知
    // （4）审批成功，给工作交接人通知
    // （5）表的结构还要优化一下
    // （6）补充查询审批进度的测试案例
    // （7）如果任务处理人离职了，要把任务转交给新的人
    // TODO

    @GetMapping("/testFullFlow")
    public ApiResponse<Void> testFullFlow() {
        // 发起流程
        // 准备流程变量
        log.info("流程测试：开始发起流程");
        LeaveApplyCreateRequest leaveApply = new LeaveApplyCreateRequest();
        leaveApply.setEmployeeId(LeaveApplyConstants.employeeId);
        leaveApply.setStartDate(new Date());
        leaveApply.setEndDate(new Date());
        leaveApply.setDays(5);
        leaveApply.setReason("婚假");
        leaveApply.setLeaderId("10087");
        leaveApply.setPmId("10087");
        leaveApply.setSupervisorId("10087");
        leaveApply.setHandoverPerson(LeaveApplyConstants.handoverPerson);

        LeaveApplyResponse data = leaveApplyAppService.apply(leaveApply).getData();
        String processInstanceId = data.getProcessInstanceId();
        log.info("流程测试：结束发起流程，流程id：{}",processInstanceId);

        log.info("流程测试：开始查询我申请的记录");
        Pagination pagination = new Pagination();
        pagination.setPageSize(1);
        pagination.setPageNumber(100);
        LeaveApplyQueryRequest queryRequest = new LeaveApplyQueryRequest();
        queryRequest.setEmployeeId(LeaveApplyConstants.employeeId);
        List<LeaveApplyQueryResponse> mineApplyList = leaveApplyAppService.query(pagination, queryRequest).getData().getList();
        log.info("流程测试：结束查询我申请的记录，结果：{}",mineApplyList);


        log.info("流程测试：开始组长审批");
        // 遍历所有组长，先查询有没有任务，然后审批处理
        List<EmployeeInfo> zuzhangs = employeeInfoService.queryEmpsByRoleKey("zuzhang").getData();

        for (EmployeeInfo employeeInfo : zuzhangs) {
            String employeeId = employeeInfo.getEmployeeId();
            String employeeName = employeeInfo.getEmployeeName();
            List<Task> tasksByAssignee = CamundaUtils.getTasksByAssigneeAndProcess(employeeId, processInstanceId, 1, 10);
            if(ObjectUtil.isEmpty(tasksByAssignee)){
                continue;
            }

            String taskId = tasksByAssignee.get(0).getId();
            log.info("流程测试：{} 有待审批的任务，任务id是{}",employeeName,taskId);
            LeaveApplyApproveRequest approvalRecordDTO = new LeaveApplyApproveRequest();
            approvalRecordDTO.setApproverId(employeeId);
            approvalRecordDTO.setApprovalResult(true);
            approvalRecordDTO.setApprovalReason(employeeName+"说同意");
            approvalRecordDTO.setProcessInstanceId(processInstanceId);
            approvalRecordDTO.setTaskId(taskId);
            leaveApplyAppService.approve(approvalRecordDTO);
            log.info("流程测试：{} 完成审批，审批结果是{}",employeeName,approvalRecordDTO.getApprovalResult());
        }

        log.info("流程测试：结束组长审批");

        log.info("流程测试：开始项目经理审批");
        // 遍历所有组长，先查询有没有任务，然后审批处理
        List<EmployeeInfo> jinglis = employeeInfoService.queryEmpsByRoleKey("jingli").getData();

        for (EmployeeInfo employeeInfo : jinglis) {
            String employeeId = employeeInfo.getEmployeeId();
            String employeeName = employeeInfo.getEmployeeName();
            List<Task> tasksByAssignee = CamundaUtils.getTasksByAssigneeAndProcess(employeeId, processInstanceId, 1, 10);
            if(ObjectUtil.isEmpty(tasksByAssignee)){
                continue;
            }

            String taskId = tasksByAssignee.get(0).getId();
            log.info("流程测试：{} 有待审批的任务，任务id是{}",employeeName,taskId);
            LeaveApplyApproveRequest approvalRecordDTO = new LeaveApplyApproveRequest();
            approvalRecordDTO.setApproverId(employeeId);
            if(ObjectUtil.equals(employeeName,"项目经理2")){
                approvalRecordDTO.setApprovalResult(false);
                approvalRecordDTO.setApprovalReason(employeeName+"说不同意");
            } else {
                approvalRecordDTO.setApprovalResult(true);
                approvalRecordDTO.setApprovalReason(employeeName+"说同意");
            }
            approvalRecordDTO.setProcessInstanceId(processInstanceId);
            approvalRecordDTO.setTaskId(taskId);
            leaveApplyAppService.approve(approvalRecordDTO);
            log.info("流程测试：{} 完成审批，审批结果是{}",employeeName,approvalRecordDTO.getApprovalResult());
        }

        log.info("流程测试：结束项目经理审批");

        log.info("流程测试：开始主管审批");
        // 遍历所有组长，先查询有没有任务，然后审批处理
        List<EmployeeInfo> zhuguans = employeeInfoService.queryEmpsByRoleKey("zhuguan").getData();

        for (EmployeeInfo employeeInfo : zhuguans) {
            String employeeId = employeeInfo.getEmployeeId();
            String employeeName = employeeInfo.getEmployeeName();
            List<Task> tasksByAssignee = CamundaUtils.getTasksByAssigneeAndProcess(employeeId, processInstanceId, 1, 10);
            if(ObjectUtil.isEmpty(tasksByAssignee)){
                continue;
            }

            String taskId = tasksByAssignee.get(0).getId();
            log.info("流程测试：{} 有待审批的任务，任务id是{}",employeeName,taskId);
            LeaveApplyApproveRequest approvalRecordDTO = new LeaveApplyApproveRequest();
            approvalRecordDTO.setApproverId(employeeId);
            approvalRecordDTO.setApprovalResult(true);
            approvalRecordDTO.setApprovalReason(employeeName+"说同意");
            approvalRecordDTO.setProcessInstanceId(processInstanceId);
            approvalRecordDTO.setTaskId(taskId);
            leaveApplyAppService.approve(approvalRecordDTO);
            log.info("流程测试：{} 完成审批，审批结果是{}",employeeName,approvalRecordDTO.getApprovalResult());
        }

        log.info("流程测试：结束主管审批");


        return ApiResponse.ok();
    }

    // 获取我提交的申请
    @GetMapping("/queryMyApply")
    @Operation(summary = "分页查询请假申请表", description = "分页查询请假申请表")
    public ApiPageResponse<LeaveApplyQueryResponse> queryMyApply(@Valid Pagination pagination,
                                                           @Valid LeaveApplyQueryRequest queryRequest) {
        return leaveApplyAppService.queryMyApply(pagination, queryRequest);
    }
    // 获取我待审核的任务
    @GetMapping("/queryToApprovelApply")
    @Operation(summary = "获取我待审核的任务", description = "获取我待审核的任务")
    public ApiPageResponse<LeaveApplyQueryResponse> queryToApprovelApply(@Valid Pagination pagination,
                                                                 @Valid LeaveApplyQueryRequest queryRequest) {
        return leaveApplyAppService.queryToApprovelApply(pagination, queryRequest);
    }

    // 获取我已审核的任务
    @GetMapping("/queryApproveledApply")
    @Operation(summary = "获取我已审核的任务", description = "获取我已审核的任务")
    public ApiPageResponse<LeaveApplyQueryResponse> queryApproveledApply(@Valid Pagination pagination,
                                                                 @Valid LeaveApplyQueryRequest queryRequest) {
        return leaveApplyAppService.queryApproveledApply(pagination, queryRequest);
    }

    // 获取申请的处理详情

}
